#include <gtk/gtk.h>

#include "library.h"
#include "mpdmodel.h"

//embedded ui.xml
extern char ui[];
extern guint ui_length;

static void
popup_menu(GtkWidget *widget)
{
	GtkMenu *menu = gtk_menu_get_for_attach_widget(widget)->data;
	gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
}

static gboolean
button_press(GtkWidget *widget, GdkEventButton *event)
{
	if(event->button == 3){
		popup_menu(widget);
	}
	return FALSE;
}

static void
on_add(Library *library)
{
	GtkTreeModel *model = gtk_tree_view_get_model(library->tv);
	GtkTreeIter iter;
	GtkTreePath *path = NULL;

	gtk_tree_view_get_cursor (library->tv, &path, NULL);
	if(!path)
		return;

	if(!gtk_tree_model_get_iter(model, &iter, path))
		return;
	gtk_tree_path_free(path);

	GValue *value = g_new0(GValue, 1);
	gtk_tree_model_get_value(model, &iter, DB_COLUMN_PATH, value);
	mpd_playlist_add(library->mpd, (char*)g_value_get_string(value));
	g_value_unset(value);
	g_free(value);
}

static void
on_replace(Library *library)
{
	MpdObj *mpd = library->mpd;
	mpd_playlist_clear(mpd);
	on_add(library);
	mpd_player_play(mpd);
}

static void
on_info(GtkTreeView *tv)
{
}

static void
path_list_fill (GtkTreeView *tree_view, GtkTreePath *path, GList** list)
{
	*list = g_list_append(*list, g_boxed_copy(GTK_TYPE_TREE_PATH, path));
}

static void
path_list_free (gpointer data)
{
	g_boxed_free(GTK_TYPE_TREE_PATH, data);
}

struct _TreeState {
	GList *expanded;
	gdouble vshift;
	GtkTreePath *cursor;
};

TreeState* 
library_save_tree_state(GtkTreeView *tv)
{
	TreeState *retval = g_new0(TreeState, 1);

	//expanded
	gtk_tree_view_map_expanded_rows(tv, (GtkTreeViewMappingFunc)path_list_fill, &retval->expanded);

	//vertical shift
	GtkAdjustment *vadj = gtk_tree_view_get_vadjustment(tv);
	retval->vshift = gtk_adjustment_get_value(vadj);

	//cursor
	gtk_tree_view_get_cursor(tv, &retval->cursor, NULL);

	return retval;
}

void
library_restore_tree_state(GtkTreeView *tv, TreeState *state)
{
	//restore expanded rows
	for(GList *it = state->expanded; it; it=it->next){
		gtk_tree_view_expand_to_path(tv, it->data);
	}
	g_list_foreach(state->expanded, (GFunc)path_list_free, NULL);
	g_list_free(state->expanded);

	//restore vertical shift
	GtkAdjustment *vadj = gtk_tree_view_get_vadjustment(tv);
	gtk_adjustment_set_value(vadj, state->vshift);
	gtk_adjustment_value_changed(vadj);

	g_free(state);
}

void
library_db_changed(Library* library)
{
	TreeState *state = library_save_tree_state(library->tv);

	//replace model
	MpdModel *mpdmodel = mpdmodel_new(library->mpd);
	gtk_tree_view_set_model(library->tv, GTK_TREE_MODEL(mpdmodel));
	g_object_unref(mpdmodel);

	library_restore_tree_state(library->tv, state);
}

Library* 
library_new(MpdObj *mpd, GtkWindow* parent)
{
	GladeXML *menu_xml = glade_xml_new_from_buffer(ui, ui_length-1, "library-menu", NULL);
	GtkWidget *menu = glade_xml_get_widget(menu_xml, "library-menu");
	GtkWidget *add = glade_xml_get_widget(menu_xml, "add");
	GtkWidget *replace = glade_xml_get_widget(menu_xml, "replace");
	GtkWidget *info = glade_xml_get_widget(menu_xml, "info");

	GladeXML *tv_xml = glade_xml_new_from_buffer(ui, ui_length-1, "library-sw", NULL);
	GtkWidget *tv_w = glade_xml_get_widget(tv_xml, "library");
	GtkTreeView *tv = GTK_TREE_VIEW(tv_w);

	Library *library = g_object_new(TYPE_LIBRARY, NULL);
	library->mpd = mpd;
	library->tv = tv;

	gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(library)->vbox),
								glade_xml_get_widget(tv_xml, "library-sw"));
	gtk_window_set_transient_for(GTK_WINDOW(library), GTK_WINDOW(parent));
	gtk_tree_view_insert_column_with_attributes(tv, -1, "Name", gtk_cell_renderer_text_new(),
												"text", DB_COLUMN_NAME,
												NULL);	
	gtk_tree_view_set_model(tv, GTK_TREE_MODEL(mpdmodel_new(mpd)));
	gtk_menu_attach_to_widget (GTK_MENU (menu), tv_w, NULL);


	GtkTargetEntry can_send[] = {
		{"splayer-db-path", GTK_TARGET_SAME_APP, 0},
	};
	gtk_tree_view_enable_model_drag_source(tv, GDK_BUTTON1_MASK, 
										   can_send, G_N_ELEMENTS(can_send), 
										   GDK_ACTION_MOVE|GDK_ACTION_COPY);

	g_signal_connect(tv, "popup-menu", (GCallback)popup_menu, menu);
	g_signal_connect(tv, "button-press-event", (GCallback)button_press, NULL);
	g_signal_connect_swapped(info, "activate", (GCallback)on_info, library);
	g_signal_connect_swapped(add, "activate", (GCallback)on_add, library);
	g_signal_connect_swapped(replace, "activate", (GCallback)on_replace, library);

	g_object_unref(menu_xml);
	g_object_unref(tv_xml);

	return library;
}

static void
library_init(Library* library)
{
}

static void
library_class_init(LibraryClass* class)
{
	GTK_WIDGET_CLASS(class)->delete_event = (void*)gtk_widget_hide_on_delete;
}

G_DEFINE_TYPE(Library, library, GTK_TYPE_DIALOG);
